
class dgParticle {
  float x;
  float y;
  float inc[];
  float way[];
  int w;
  dgParticle() {}
  dgParticle(int windowW,int windowH) {
    this.x = windowW/2;
    this.y = windowH/2;
    this.w = windowW/20;
    this.inc = new float[]{this.w*sin(random(1)-0.5),this.w*sin(random(1)-0.5),0};
    this.way = new float[]{random(1),random(1),0};
  }
  void createParticle(int windowW,int windowH) {
    this.x = windowW/2;
    this.y = windowH/2;
    this.inc = new float[]{this.w*sin(random(1)-0.5),this.w*sin(random(1)-0.5),0};
    this.way = new float[]{random(1),random(1),0};
  }
  void drawIt(int windowW,int windowH) {
    fill(this.way[0]*255,255,this.way[1]*255);
    ellipseMode(CENTER);
    ellipse(this.x,this.y,windowW/40,windowH/40);
  }
  void moveIt(int windowW,int windowH) {
//    if ((this.x<1)&&(this.inc[0]<0)) {this.inc[0] *= -1;}
//    if ((this.y<1)&&(this.inc[1]<0)) {this.inc[1] *= -1;}
//    if ((this.x>windowW-1)&&(this.inc[0]>0)) {this.inc[0] *= -1;}
//    if ((this.y>windowH-1)&&(this.inc[1]>0)) {this.inc[1] *= -1;}
    this.x += this.inc[0];// + this.way[0];
    this.y += this.inc[1];// + this.way[1];
  }
}

class dgParticleSystem {
  int numOfParticles;
  dgParticle[] particles;
  boolean[] particleActive;
  dgParticleSystem() {}
  dgParticleSystem(int numOfParticlesToCreate,int windowW,int windowH) {
    int i=0;
    particles = new dgParticle[200];
    particleActive = new boolean[200];
    for (i=0;i<numOfParticlesToCreate;i++) {
      particles[i] = new dgParticle(windowW,windowH);
      particleActive[i] = true;
    }
    for (i=numOfParticlesToCreate;i<200;i++) particleActive[i] = false;
    numOfParticles = numOfParticlesToCreate;
  }
  void drawThem(int windowW,int windowH) {
    boolean recreate=false;
    for (int i=0;i<numOfParticles;i++)
      if (particleActive[i]) {
        particles[i].moveIt(windowW,windowH);
        particles[i].drawIt(windowW,windowH);
        if ((particles[i].x<1)||(particles[i].y<1)||(particles[i].x>windowW-1)||(particles[i].y>windowH-1)) {
          particles[i].createParticle(windowW,windowH);
          recreate = true;
        }
        if (absD(particles[i].inc[0])+absD(particles[i].inc[1])<particles[i].w/2) {
          particles[i].createParticle(windowW,windowH);
          recreate = true;
        }
      }
      if ((!recreate)&&(numOfParticles<200)) {
        particles[numOfParticles] = new dgParticle(windowW,windowH);
        particleActive[numOfParticles] = true;
        numOfParticles++;
      }
      
  }
}

dgParticleSystem myParticleSystem;
int numOfParts=1;
void setup () {
  int i=0;
  size(400,400);
  myParticleSystem = new dgParticleSystem(numOfParts,width,height);
  PFont myFont = createFont("verdana", 24);
  textFont(myFont);
}

void draw() {
  int i=0;
  background(0);
  myParticleSystem.drawThem(width,height);
  fill(255);
  text(myParticleSystem.numOfParticles,width/2,height/2);  
}

float absD(float x) {
  if (x>=0) return x;
  return -x;
}
float DogaDotProduct(float V1[],float V2[]) {return V1[0]*V2[0]+V1[1]*V2[1]+V1[2]*V2[2];}
float DogaMakeUnitVector(float V[]) {
  float w=0;
  w = sqrt(DogaDotProduct(V,V));
  if (w!=0) {
    V[0] = V[0]/w;
    V[1] = V[1]/w;
    V[2] = V[2]/w;
  }
  else {
    V[0] = 0;
    V[1] = 0;
    V[2] = 0;
  }
  return w;
}

 //   if (noise(this.way[0]*this.way[1],this.x*this.y,this.inc[0]*this.inc[1])>0.5) this.way[0] += 0.2;
 //   else this.way[1] += 0.2;
 //   DogaMakeUnitVector(this.way);
 //   this.incX += this.way[0];
 //   this.incY += this.way[1];
